package org.apache.rocketmq.client.java.impl;

import apache.rocketmq.v2.Settings;
import com.google.common.base.MoreObjects;
import com.google.common.util.concurrent.SettableFuture;
import org.apache.rocketmq.client.java.retry.RetryPolicy;
import org.apache.rocketmq.client.java.route.Endpoints;

import java.time.Duration;

/**
 * @课程描述:从零带你写框架系列中的课程，整个系列包含netty，xxl-job，rocketmq，nacos，sofajraft，spring，springboot，disruptor，编译器，虚拟机等等。
 * @author：陈清风扬，个人微信号：chenqingfengyangjj。
 * @date:2025/6/10
 * @方法描述：客户端设置抽象基类，为如生产者、消费者客户端提供通用的配置参数
 */
public abstract class ClientSettings {

    //客户端唯一Id
    protected final String clientId;

    //客户端类型，表示当前客户端是生产者客户端还是消费者客户端
    protected final ClientType clientType;

    //该成员变量封装了客户端可以访问的服务端的所有网络地址
    protected final Endpoints accessPoint;

    //请求失败的重试策略，用于处理客户端发送请求失败时的重试机制
    protected volatile RetryPolicy retryPolicy;

    //请求超时时间
    protected final Duration requestTimeout;

    //这个future对象会在服务端回复给客户端响应后被设置为完成状态
    //每次客户端给服务端发送了TelemetryCommand请求之后，服务端处理了该请求之后
    //会给客户端回复一个TelemetryCommand请求，在客户端的ClientSessionImpl会话对象的onNext方法中会接收到
    //服务端回复的响应，然后会调用arrivedFuture的setFuture方法，将arrivedFuture对象设置为完成状态
    protected final SettableFuture<Void> arrivedFuture;

    //构造方法
    public ClientSettings(String clientId, ClientType clientType, Endpoints accessPoint,
                          RetryPolicy retryPolicy, Duration requestTimeout) {
        this.clientId = clientId;
        this.clientType = clientType;
        this.accessPoint = accessPoint;
        this.retryPolicy = retryPolicy;
        this.requestTimeout = requestTimeout;
        this.arrivedFuture = SettableFuture.create();
    }


    //构造方法
    public ClientSettings(String clientId, ClientType clientType, Endpoints accessPoint, Duration requestTimeout) {
        this(clientId, clientType, accessPoint, null, requestTimeout);
    }


    //将客户端的配置参数信息转换为Protocol Buffer格式的Settings对象的方法
    public abstract Settings toProtobuf();

    //应用从服务端发送过来的客户端配置参数的方法
    public abstract void applySettingsCommand(Settings settings);

    //获取当前重试策略的方法
    public RetryPolicy getRetryPolicy() {
        return retryPolicy;
    }

    //获取客户端设置到达服务端后完成异步等待的Future对象
    public SettableFuture<Void> getArrivedFuture() {
        return arrivedFuture;
    }


    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("clientId", clientId)
                .add("clientType", clientType)
                .add("accessPoint", accessPoint)
                .add("retryPolicy", retryPolicy)
                .add("requestTimeout", requestTimeout)
                .toString();
    }
}
